<?php
/**
 * http.class.php
 * 
 * 处理文件加载. 文件下载等相关功能
 * 
 * @author lsl8966 <470663151@qq.com> 
 * @copyright Copyright (c) 2012 lsl8966 Software Studio
 * @link http://www.cnblogs.com/lsl8966
 * @version $Id: AutoLoad.class.php 1.0 2012-12-18 22:48:01Z lsl8966 $
 * @package lib
 * @since 1.0
 */
if (!defined('IN_PDK')){
     exit();
    }

class http extends Base{
    
    /**
     * http下载文件
     * 
     * Reads a file and send a header to force download it.
     * 
     * @copyright www.doophp.com
     * @param string $file_str File name with absolute path to it
     * @param bool $isLarge If True, the large file will be read chunk by chunk into the memory.
     * @param string $rename Name to replace the file name that would be downloaded
     */
     public static function download($file, $isLarge = false, $rename = NULL){
        
         if(headers_sent())return false;
        
         if(!$file){
             exit('Error 404:The file not found!');
             }
        
         if($rename == NULL){
             if(strpos($file, '/') === false && strpos($file, '\\') === false)
                 $filename = $file;
             else{
                 $filename = basename($file);
                 }
             }else{
             $filename = $rename;
             }
        
         header('Content-Description: File Transfer');
         header('Content-Type: application/octet-stream');
         header("Content-Disposition: attachment; filename=\"$filename\"");
         header('Expires: 0');
         header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
         header('Pragma: public');
         header('Content-Length: ' . filesize($file));
         ob_clean();
         flush();
        
         if($isLarge)
             self :: readfileChunked($file);
         else
             readfile($file);
         }
    
    /**
     * Read a file and display its content chunk by chunk
     * 
     * @param string $filename 
     * @param bool $retbytes 
     * @return mixed 
     */
     private function readfileChunked($filename, $retbytes = true, $chunkSize = 1024){
        
         $buffer = '';
         $cnt = 0;
        
         $handle = fopen($filename, 'rb');
         if ($handle === false){
             return false;
             }
         while (!feof($handle)){
             $buffer = fread($handle, $chunkSize);
             echo $buffer;
             ob_flush();
             flush();
             if ($retbytes){
                 $cnt += strlen($buffer);
                 }
             }
         $status = fclose($handle);
         if ($retbytes && $status){
             return $cnt; // return num. bytes delivered like readfile() does.
             }
        
         return $status;
         }
    
    /**
     * HTTP状态信息数组
     * 
     * @var array 
     */
     public  static $_httpStatus = array(
        
         '100' => 'Continue',
         '101' => 'Switching Protocols',
        
         '200' => 'OK',
         '201' => 'Created',
         '202' => 'Accepted',
         '203' => 'Non-Authoritative Information',
         '204' => 'No Content',
         '205' => 'Reset Content',
         '206' => 'Partial Content',
        
         '300' => 'Multiple Choices',
         '301' => 'Moved Permanently',
         '302' => 'Found',
         '303' => 'See Other',
         '304' => 'Not Modified',
         '305' => 'Use Proxy',
         '306' => '(Unused)',
         '307' => 'Temporary Redirect',
        
         '400' => 'Bad Request',
         '401' => 'Unauthorized',
         '402' => 'Payment Required',
         '403' => 'Forbidden',
         '404' => 'Not Found',
         '405' => 'Method Not Allowed',
         '406' => 'Not Acceptable',
         '407' => 'Proxy Authentication Required',
         '408' => 'Request Timeout',
         '409' => 'Conflict',
         '410' => 'Gone',
         '411' => 'Length Required',
         '412' => 'Precondition Failed',
         '413' => 'Request Entity Too Large',
         '414' => 'Request-URI Too Long',
         '415' => 'Unsupported Media Type',
         '416' => 'Requested Range Not Satisfiable',
         '417' => 'Expectation Failed',
        
         '500' => 'Internal Server Error',
         '501' => 'Not Implemented',
         '502' => 'Bad Gateway',
         '503' => 'Service Unavailable',
         '504' => 'Gateway Timeout',
         '505' => 'HTTP Version Not Supported',

         '601' => 'Account Not Found',
         '602' => 'Incorrect password',
         '40000' => 'Invalid Parameter',
         '40001' => 'Invalid credential',
        );
    
    /**
     * 设置HTTP状态信息
     * 
     * @access public 
     * @param string $code HTTP 状态编码
     * @param string $name HTTP 状态信息
     * @return string 
     */
     public static function httpStatus($code, $text = null){
         // 获取http协议
        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
         $text = is_null($text) ? self :: $_httpStatus[$code] : $text;
         $status = "$protocol $code $text";
        
         header($status);
     }

    /**
     * 获取IP地址
     * @param bool $had_frowarded
     * @return string
     */
    public static function getIp(&$had_frowarded = false ){
        if(isset($HTTP_SERVER_VARS) && $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])
        {
            $ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
            $had_frowarded = true;
        }
        elseif($HTTP_SERVER_VARS["HTTP_CLIENT_IP"])
        {
            $ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
        }
        elseif ($HTTP_SERVER_VARS["REMOTE_ADDR"])
        {
            $ip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
        }
        elseif (getenv("HTTP_X_FORWARDED_FOR"))
        {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
            $had_frowarded = true;
        }
        elseif (getenv("HTTP_CLIENT_IP"))
        {
            $ip = getenv("HTTP_CLIENT_IP");
        }
        elseif (getenv("REMOTE_ADDR"))
        {
            $ip = getenv("REMOTE_ADDR");
        }
        else
        {
            $ip = "Unknown";
        }
        return $ip;
    }
}
